package com.frank.oj.core.dispatcher;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.frank.model.dto.TestJudgeReq;
import com.frank.model.entity.judge.Judge;
import com.frank.oj.common.exception.StatusSystemErrorException;
import com.frank.oj.constant.Constants;
import com.frank.oj.core.receiver.JudgeReceiver;
import com.frank.oj.service.entity.judge.JudgeEntityService;
import com.frank.oj.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author frank
 * @Date 2024/4/15
 */
@Component
@RefreshScope
@Slf4j(topic = "hcoj")
public class JudgeDispatcher {
    @Resource
    private RedisUtils redisUtils;

    @Resource
    private JudgeEntityService judgeEntityService;

    @Resource
    private JudgeReceiver judgeReceiver;

    @Value("${judge-token}")
    private String judgeToken;
    public void sendTestJudgeTask(TestJudgeReq testJudgeReq) throws StatusSystemErrorException {
        testJudgeReq.setToken(judgeToken);

        try {
            // 将判题信息（代码···）加入redis队列
            boolean isOk = redisUtils.llPush(Constants.Queue.TEST_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(testJudgeReq));
            if (!isOk) {
                throw new StatusSystemErrorException("系统错误：当前评测任务加入等待队列失败！");
            }
            judgeReceiver.processWaitingTask();
        } catch (Exception e) {
            log.error("调用redis将判题纳入判题等待队列异常--------------->{}", e.getMessage());
            throw new StatusSystemErrorException("系统错误：当前评测任务加入等待队列失败！");
        }
    }

    public void sendTask(Long judgeId, Long pid, boolean isContest) {
        JSONObject task = new JSONObject();
        task.set("judgeId", judgeId);
        task.set("token", judgeToken);
        task.set("isContest", isContest);

        try {
            boolean isOK;
            if (isContest){
                isOK=redisUtils.llPush(Constants.Queue.CONTEST_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(task));
            }else {
                isOK = redisUtils.llPush(Constants.Queue.GENERAL_JUDGE_WAITING.getName(), JSONUtil.toJsonStr(task));
            }

            if (!isOK) {
                judgeEntityService.updateById(new Judge()
                        .setSubmitId(judgeId)
                        .setStatus(Constants.Judge.STATUS_SUBMITTED_FAILED.getStatus())
                        .setErrorMessage("Call Redis to push task error. Please try to submit again!")
                );
            }

            judgeReceiver.processWaitingTask();
        }catch (Exception e){
            log.error("调用redis将判题纳入判题等待队列异常--------------->{}", e.getMessage());
            judgeEntityService.failToUseRedisPublishJudge(judgeId, pid, isContest);
        }
    }
}
